package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.junit.runner.Runner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Map;

/**
 * @Author: 生如夏花
 * @Date: 2022/3/8 20:08
 */
@SpringBootTest
@RunWith (SpringRunner.class)
public class HotelSearchDemo {

    @Autowired
    private RestHighLevelClient client;
    private String HOTEl_STR = "hotel";
    @Test
    void testSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest (HOTEl_STR);
        searchRequest.source ().query (QueryBuilders.matchAllQuery ());
        searchRequest.source ().from (9);
        searchRequest.source ().size (1);
        SearchResponse search = client.search (searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = search.getHits ();
        SearchHit[] hotel = hits.getHits ();
        for (SearchHit documentFields : hotel) {
            HotelDoc jsonObject = JSON.parseObject (documentFields.getSourceAsString (), HotelDoc.class);
            System.out.println (jsonObject);
        }
    }
    @Test
    void testMatch() throws IOException {
        SearchRequest searchRequest = new SearchRequest (HOTEl_STR);
        //match查询 单字段
        searchRequest.source ().query (QueryBuilders.matchQuery ("city","上海"));
        //multi_match查询 多字段
        searchRequest.source ().query (QueryBuilders.multiMatchQuery ("七天","brand","name"));
        SearchResponse search = client.search (searchRequest, RequestOptions.DEFAULT);
        System.out.println (search);
    }
    @Test
    void testTermAndRangeQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest (HOTEl_STR);
        //term查询 精确查询
        searchRequest.source ().query (QueryBuilders.termQuery ("brand","如家"));
        //range查询 范围查询
        searchRequest.source ().query (QueryBuilders.rangeQuery ("price").gte (100).lte (500));
        SearchResponse search = client.search (searchRequest, RequestOptions.DEFAULT);
        System.out.println (search);
    }
    @Test
    void testBooleanQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest (HOTEl_STR);
        //创建boolean查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery ();
        //must条件
        boolQueryBuilder.must (QueryBuilders.matchQuery ("city","上海"));
        //filter条件
        boolQueryBuilder.filter (QueryBuilders.matchQuery ("brand","如家"));
        searchRequest.source ().query (boolQueryBuilder);
        SearchResponse search = client.search (searchRequest, RequestOptions.DEFAULT);
        System.out.println (search);
    }
    @Test
    void testPageAndSort() throws IOException {
        SearchRequest searchRequest = new SearchRequest (HOTEl_STR);
        searchRequest.source ().query (QueryBuilders.matchAllQuery ());
        //查询文档起始位置
        searchRequest.source ().from (10);
        //查询文档数
        searchRequest.source ().size (10);
        //排序
        searchRequest.source ().sort ("price", SortOrder.ASC);
        SearchResponse search = client.search (searchRequest, RequestOptions.DEFAULT);
        System.out.println (search);
    }
    @Test
    void testHighlighter() throws IOException {
        SearchRequest searchRequest = new SearchRequest (HOTEl_STR);
        //对name和brand字段进行高亮
        searchRequest.source ().highlighter (new HighlightBuilder ().field ("name").field ("brand").requireFieldMatch (false));
        searchRequest.source ().query (QueryBuilders.matchQuery ("all","如家"));
        SearchResponse search = client.search (searchRequest, RequestOptions.DEFAULT);
        //高亮结果处理
        SearchHit[] hits = search.getHits ().getHits ();
        TotalHits totalHits = search.getHits ().getTotalHits ();
        System.out.println (totalHits.value);
        for (SearchHit hit : hits) {
            HotelDoc hotelDoc = JSON.parseObject (hit.getSourceAsString (), HotelDoc.class);
            Map<String, HighlightField> highlightFields = hit.getHighlightFields ();
            if (!CollectionUtils.isEmpty (highlightFields)){
                HighlightField highlightField = highlightFields.get ("name");
                if (highlightField != null){
                    String name = highlightField.getFragments ()[0].string ();
                    hotelDoc.setName (name);
                }
                HighlightField highlightFieldBrand = highlightFields.get ("brand");
                if (highlightFieldBrand != null){
                    String brand = highlightFieldBrand.getFragments ()[0].string ();
                    hotelDoc.setBrand (brand);
                }
                System.out.println (hotelDoc);
            }
        }

    }
//    @BeforeEach
//    void init(){
//        client = new RestHighLevelClient (RestClient.builder (
//                HttpHost.create ("http://47.108.68.42:9200")
//        ));
//    }
//
//    @AfterEach
//    void close() throws IOException {
//        client.close ();
//    }
}
